﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Forms;

namespace BackUpAnyWhere
{
    public class FileHandle
    {
        private List<string> FileDeleteList;

        private string SourcePath;
        private string DestinationPath;
        private string[] SourceFileList;
        private string[] SourceDirectoryList; 
        private string[] DestinationFileList;
        private string[] DestinationDirectoryList;

        private int NumOfDayForOld = 30;
        public int[] FileCounter = new int[7];


        public FileHandle(string _SourcePath, string _DestinationPath)
        {
            FileDeleteList = new List<string>();
            SourcePath = _SourcePath;
            DestinationPath = _DestinationPath;

            for (int index = 0; index < FileCounter.Length; index++)
                FileCounter[index] = 0;
        }

        public FileHandle()
        {
            FileDeleteList = new List<string>();
            SourcePath = null;
            DestinationPath = null;

            for (int index = 0; index < FileCounter.Length; index++)
                FileCounter[index] = 0;
        }

        public void setSourcePath(string path)
        {
            SourcePath = path;
        }
        public string getSourcePath()
        {
            return (SourcePath);
        }

        public String getDestinationPath()
        {
            return (DestinationPath);
        }

        public void SetDestinationPath(string path)
        {
            DestinationPath = path;
        }

        public int getFileCounter(int CounterID)
        {
            return FileCounter[CounterID];
        }
        public void setFileCounter(int CounterID, int Count)
        {
            FileCounter[CounterID] = Count;
        }

        public bool IsFileExist(string file)
        {
            if (File.Exists(file))
                return true;
            
            return false;
        }
        public static bool isDirExist(string DirName)
        {
            if (Directory.Exists(DirName))
                return true;

            return false;
        }

        public DateTime getFileWrittenTime(String file)
        {
            return (File.GetLastWriteTime(file));
        }

        public DateTime getFileCreateTime(String file)
        {
            return (File.GetCreationTime(file));
        }

        public string[] get_file_list()
        {
            SourceFileList = Directory.GetFiles(SourcePath);
            return (SourceFileList);
        }

        public String[] Get_DestinationFileList()
        {
            DestinationFileList = Directory.GetFiles(DestinationPath);
            return (DestinationFileList);
        }

        public String[] Get_Dirctory_list()
        {
            SourceDirectoryList = Directory.GetDirectories(SourcePath);
            return (SourceDirectoryList);
        }

        public String[] Get_Dirctory_list_from_the_distination()
        {
            DestinationDirectoryList = Directory.GetDirectories(DestinationPath);
            return (DestinationDirectoryList);
        }

        public static void CreateDirectory(string dir)
        {
            Directory.CreateDirectory(dir);
        }


        /* ----------------------------------------------------------------------------------------------------------------------- */
        public void FileCopyAndSync()
        {
            /*
             * copy all the file and directory form the source to the destination. if the destination folder 
             * isn't exist the function will create it and after that copy the file to the folder,
             * if there are directories in the source folder it will copy the directory from the source folder
             * by call to the function again with a new parameters. the function also can sync the directory
             * by compare the date of the last time the file was write and by check if the file exist
             */

            string DestinationFileName = null;
            SourceFileList = Directory.GetFiles(SourcePath);
            SourceDirectoryList = Directory.GetDirectories(SourcePath);

            setFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileExist, 
                            Directory.GetFiles(SourcePath).Length + getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileExist));
            
            if (!isDirExist(DestinationPath))
                CreateDirectory(DestinationPath);

            foreach (string FileToCopy in SourceFileList)
            {
                BackUpForm.NotificationUpdate((int)BackUpAnyWhere.Program.NotificationType.FileUpdate);
                DestinationFileName = DestinationPath + FileToCopy.Substring(SourcePath.Length);

                // First check if the current file exist at the destination
                if (!IsFileExist(DestinationFileName))
                {
                    // if not, them try copy it 
                    try
                    {
                        File.Copy(FileToCopy, DestinationFileName);
                        setFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileCopy, getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileCopy) + 1);
                    }
                    catch
                    {
                        setFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileCouldNotCopeid, getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileCouldNotCopeid) + 1);
					}
                }
                else
                {
                    // if yes, then check it date. if the local file is newer then the destination file
                    // then try overwrite the destination file
                    DateTime SourceFileDateTime, DestinationFileDateTime;
                    if ((SourceFileDateTime = getFileWrittenTime(FileToCopy)) > (DestinationFileDateTime = getFileWrittenTime(DestinationFileName)))
                    {
                        try
                        {
                            File.Copy(FileToCopy, DestinationFileName, true);
                            setFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileSync, getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileSync) + 1);
						}
						catch
						{
                            setFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileCouldNotCopeid, getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileCouldNotCopeid) + 1);
                        }
                    }
                    else
                        setFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileNotCopeid, getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileNotCopeid) + 1);
                }
            }

            string DestinationSubDir = null;
            foreach (string SourceSubDir in SourceDirectoryList)
            {
                DestinationSubDir = DestinationPath + SourceSubDir.Substring(SourcePath.Length);
                FileHandle CopyFileObj = new FileHandle(SourceSubDir, DestinationSubDir);
                CopyFileObj.FileCopyAndSync();
                setFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileCopy, (getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileCopy) + CopyFileObj.getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileCopy)));
                setFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileSync, getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileSync) + CopyFileObj.getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileSync));
                setFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileNotCopeid, getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileNotCopeid) + CopyFileObj.getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileNotCopeid));
                setFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileExist, getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileExist) + CopyFileObj.getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileExist));
            }
        }

        /* ----------------------------------------------------------------------------------------------------------------------- */
        public List<string> Chack_syc()
        {
            DestinationFileList = Directory.GetFiles(DestinationPath);
            DestinationDirectoryList = Directory.GetDirectories(DestinationPath);

            foreach (string FileName in DestinationFileList)
            {
                if (isFileTooOld(FileName))
                {
                    FileDeleteList.Add(FileName);
                    setFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileToDelete, getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileToDelete) + 1);
                }
            }

            foreach (string DestinationSubDir in DestinationDirectoryList)
            {
                FileHandle CopyFileObj = new FileHandle(SourcePath, DestinationSubDir);
                FileDeleteList.AddRange(CopyFileObj.Chack_syc());
                setFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileToDelete, getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileToDelete) + CopyFileObj.getFileCounter((int)BackUpAnyWhere.Program.FileCounterType.FileToDelete));
            }
            return FileDeleteList;
        }

        private bool isFileTooOld(string FileName)
        {
            DateTime CurrentTime = DateTime.Now;
            DateTime FileCreateTime = getFileCreateTime(FileName);
            DateTime FileChangeTime = getFileWrittenTime(FileName);

            if ((CurrentTime.Subtract(FileCreateTime).Days > NumOfDayForOld) &&
                (CurrentTime.Subtract(FileChangeTime).Days > NumOfDayForOld))
                return true;

            return false;
        }

        /* ----------------------------------------------------------------------------------------------------------------------- */
        public static void DeleteFileList (List<string> FileList)
        {
            foreach (string FileToDelete in FileList)
                File.Delete(FileToDelete);
        }

        public static int GetFilesRecursive(string Path)
        {
            List<string> FileList = new List<string>();
            Stack<string> SubDirectoriesStack = new Stack<string>();

            SubDirectoriesStack.Push(Path);

            while (SubDirectoriesStack.Count > 0)
            {
                string dir = SubDirectoriesStack.Pop();
                try
                {
                    FileList.AddRange(Directory.GetFiles(dir, "*.*"));
            
                    foreach (string dn in Directory.GetDirectories(dir))
                        SubDirectoriesStack.Push(dn);
                }
                catch { }
            }
            return FileList.Count;
        }

        public static bool ValidateDirectoryName(String NewDirName)
        {
            if (NewDirName.Length == 0)
                return (false);
            if (NewDirName.Contains("?"))
                return (false);

            return (true);
        }

        public static long GetDriveUseSize(DriveInfo DriveToCheck)
        {
            return (DriveToCheck.TotalSize - DriveToCheck.AvailableFreeSpace);
        }
    }
}
